Стандарт C - размещенная среда
Для размещенной среды (это нормальная среда) стандарт C11 (ISO / IEC 9899: 2011) гласит:
5.1.2.2.1 Запуск программы
Функция, вызываемая при запуске программы, называется main
. Реализация заявляет нет
прототип для этой функции. Он должен быть определен с типом возврата int
и без
Параметры:
int main(void) { /* ... */ }
или с двумя параметрами (именуемыми здесь argc
и argv
, хотя любые имена могут быть
используется, поскольку они являются локальными для функции, в которой они объявлены):
int main(int argc, char *argv[]) { /* ... */ }
или эквивалентный; 10) или другим способом, определяемым реализацией.
Если они объявлены, параметры главной функции должны соответствовать следующим
Ограничения:
- Значение
argc
должно быть неотрицательным.
argv[argc]
должен быть нулевым указателем.
- Если значение
argc
больше нуля, элементы массива argv[0]
через
argv[argc-1]
включительно должен содержать указатели на строки, которые даны
значения, определенные реализацией средой хоста до запуска программы.
намерение состоит в том, чтобы предоставить программе информацию, определенную до ее запуска
из другого места в размещенной среде. Если среда хоста не способна
предоставление строк с буквами в верхнем и нижнем регистре, реализация
убедитесь, что строки получены в нижнем регистре.
- Если значение
argc
больше нуля, строка, на которую указывает argv[0]
представляет название программы; argv[0][0]
должен быть нулевым символом, если
Имя программы недоступно в хост-среде. Если значение argc
больше единицы строки, указанные на argv[1]
- argv[argc-1]
представляют параметры программы.
- Параметры
argc
и argv
и строки, на которые указывает массив argv
, должны
быть изменяемыми программой и сохранять их последние сохраненные значения между программами
запуск и завершение программы.
10) Таким образом, int
может быть заменено именем typedef, определенным как int
, или тип argv
может быть записан как
char **argv
и т. Д.
Завершение программы в C99 или C11
Значение, возвращаемое из main()
, передается в «среду» способом, определяемым реализацией.
5.1.2.2.3 Завершение программы
1 Если тип возврата функции main
является типом, совместимым с int
, возврат из
первоначальный вызов функции main
эквивалентен вызову функции exit
со значением
возвращается функцией main
в качестве аргумента; 11) , достигая }
, который завершает
Функция main
возвращает значение 0. Если тип возвращаемого значения не совместим с int
,
статус завершения, возвращенный в среду хоста, не указан.
11) В соответствии с 6.2.4, время жизни объектов с автоматической продолжительностью хранения объявлено в main
закончится в первом случае, даже если они не закончатся во втором.
Обратите внимание, что 0
обозначается как «успех». Вы можете использовать EXIT_FAILURE
и EXIT_SUCCESS
из <stdlib.h>
, если хотите, но 0 точно установлено, как и 1. См. Также Коды выхода больше 255 - возможно? .
В C89 (и, следовательно, в Microsoft C) нет заявления о том, что произойдет, если функция main()
вернется, но не определит возвращаемое значение; следовательно, это ведет к неопределенному поведению.
7.22.4.4 exit
функция
Finally5 Наконец, управление возвращается в среду хоста. Если значение status
равно нулю или EXIT_SUCCESS
, возвращается определяемая реализацией форма состояния успешного завершения . Если значение status
равно EXIT_FAILURE
, возвращается определяемая реализацией форма состояния неудачное завершение . В противном случае возвращаемый статус определяется реализацией.
Стандарт C ++ - размещенная среда
Стандарт C ++ 11 (ISO / IEC 14882: 2011) гласит:
3.6.1 Основная функция [basic.start.main]
¶1 Программа должна содержать глобальную функцию main, которая является назначенным началом программы. [...]
¶2 Реализация не должна предопределять основную функцию. Эта функция не должна быть перегружена. Это должно
иметь тип возвращаемого значения типа int, но в противном случае его тип определяется реализацией.
Все реализации
должно допускать оба следующих определения основных:
int main() { /* ... */ }
и
int main(int argc, char* argv[]) { /* ... */ }
В последнем виде argc
- количество аргументов, переданных программе из среды
в котором программа запускается. Если argc
отлично от нуля, эти аргументы должны быть указаны в argv[0]
через argv[argc-1]
в качестве указателей на начальные символы многобайтовых строк с нулевым символом в конце (NTMBS) (17.5.2.1.4.2) и argv[0]
должны быть указателем на начальный символ NTMBS, который представляет
имя, используемое для вызова программы или ""
. Значение argc
должно быть неотрицательным. Значение argv[argc]
должно быть 0. [Примечание: Рекомендуется добавлять любые дополнительные (необязательные) параметры после argv
. -конец
примечание]
¶3 Функция main
не должна использоваться в программе. Связь (3.5) main
определяется реализацией. [...]
¶5 Оператор возврата в main приводит к выходу из функции main (уничтожение любых объектов автоматически
длительность хранения) и вызов std::exit
с возвращаемым значением в качестве аргумента. Если контроль достигает конца
main, не встречая оператора return, эффект от выполнения
return 0;
Стандарт C ++ явно говорит: «Он [основная функция] должен иметь тип возврата типа int
, но в противном случае его тип определяется реализацией», и для поддержки в качестве опций требуются те же две сигнатуры, что и для стандарта C , Так что void main () напрямую не разрешен стандартом C ++, хотя он ничего не может сделать, чтобы остановить нестандартную реализацию, допускающую альтернативы. Обратите внимание, что C ++ запрещает пользователю звонить main
(но стандарт C этого не делает).
Есть параграф §18.5 Начало и окончание в стандарте C ++ 11, который идентичен абзацу из §7.22.4.4 Функция exit
в C11 стандарт (цитируется выше), за исключением сноски (которая просто документирует, что EXIT_SUCCESS
и EXIT_FAILURE
определены в <cstdlib>
).
Стандарт C - Общее расширение
Классически системы Unix поддерживают третий вариант:
int main(int argc, char **argv, char **envp) { ... }
Третий аргумент - это список указателей на строки с нулевым символом в конце, каждый из которых является переменной окружения, которая имеет имя, знак равенства и значение (возможно, пустое). Если вы не используете это, вы все равно можете попасть в окружение через 'extern char **environ;
'. Долгое время у этого не было заголовка, который объявил его, но стандарт POSIX 2008 теперь требует, чтобы он был объявлен в <unistd.h>
.
Это признано стандартом C как общее расширение, документированное в Приложении J:
J.5.1 Аргументы среды
¶1 В размещенной среде главная функция получает третий аргумент, char *envp[]
,
указывает на массив указателей с нулевым символом в конце char
, каждый из которых указывает на строку
который предоставляет информацию о среде для выполнения программы (5.1.2.2.1).
Microsoft C
Microsoft VS 2010 - интересный компилятор. На сайте написано:
Синтаксис объявления для main:
int main();
или, необязательно,
int main(int argc, char *argv[], char *envp[]);
Кроме того, функции main
и wmain
могут быть объявлены как возвращающие void
(без возвращаемого значения). Если вы объявляете main
или wmain
как возвращающее void, вы не можете вернуть код завершения родительскому процессу или операционной системе с помощью оператора return. Чтобы вернуть код выхода, когда main
или wmain
объявлен как void
, необходимо использовать функцию exit
.
Мне не ясно, что происходит (какой код выхода возвращается родительскому или ОС), когда программа с void main()
завершает работу - и веб-сайт MS тоже молчит.
Интересно, что MS не предписывает версию main()
с двумя аргументами, которая требуется для стандартов C и C ++. Он только предписывает форму с тремя аргументами, где третий аргумент - char **envp
, указатель на список переменных среды.
На странице Microsoft также перечислены некоторые другие альтернативы - wmain()
, которая принимает строки широких символов, и некоторые другие.
Microsoft Visual Studio 2005 версия на этой странице не перечисляет void main()
в качестве альтернативы. версии от Microsoft Visual Studio 2008 и далее.
Стандарт C - Отдельно стоящая среда
Как уже отмечалось ранее, вышеприведенные требования применяются к размещенным средам. Если вы работаете с автономной средой (которая является альтернативой размещенной среде), то о стандарте можно сказать гораздо меньше. Для автономной среды функцию, вызываемую при запуске программы, не нужно называть main
, и нет никаких ограничений на ее тип возвращаемого значения. Стандарт гласит:
5.1.2 Среда исполнения
Определены две среды исполнения: автономная и размещенная. В обоих случаях,
запуск программы происходит, когда назначенная функция C вызывается при выполнении
среда. Все объекты со статической продолжительностью хранения должны быть инициализированы (установлены их начальные значения) перед запуском программы. Способ и время такой инициализации в остальном не определены. Завершение программы возвращает управление среде выполнения.
5.1.2.1 Отдельно стоящая среда
В автономной среде (в которой выполнение программы на С может происходить без какой-либо выгоды от операционной системы), имя и тип функции, вызываемой при запуске программы, определяются реализацией. Любые библиотечные средства, доступные для автономной программы, кроме минимального набора, требуемого пунктом 4, определяются реализацией.
Эффект завершения программы в автономной среде определяется реализацией.
Перекрестная ссылка на пункт 4 Соответствие относится к этому:
¶5 A строго соответствующая программа должна использовать только те функции языка и библиотеки, которые указаны в настоящем международном стандарте. 3) Она не должна производить вывод, зависящий от каких-либо неопределенных, неопределенных или поведение, определяемое реализацией, и не должно превышать какого-либо минимального предела реализации.
¶6 Двумя формами соответствующей реализации являются hosted и freestanding . соответствующая размещенная реализация принимает любую строго соответствующую программу. соответствующая автономная реализация должна принимать любую строго соответствующую программу, в которой использование функций, указанных в разделе библиотеки (пункт 7), ограничено содержимым стандартных заголовков <float.h>
, <iso646.h>
, <limits.h>
, <stdalign.h>
,
<stdarg.h>
, <stdbool.h>
, <stddef.h>
, <stdint.h>
и
<stdnoreturn.h>
. Соответствующая реализация может иметь расширения (включая
дополнительные библиотечные функции), при условии, что они не изменяют поведение любой строго соответствующей программы. 4)
*7 Соответствующая программа является приемлемой для соответствующей реализации. 5)
3) Строго соответствующая программа может использовать условные функции (см. 6.10.8.3) при условии, что использование защищено соответствующей директивой предварительной обработки условного включения с использованием соответствующего макроса. Например:
#ifdef __STDC_IEC_559__ /* FE_UPWARD defined */
/* ... */
fesetround(FE_UPWARD);
/* ... */
#endif
4) Это означает, что соответствующая реализация не оставляет никаких идентификаторов, кроме тех, которые явно зарезервированы в этом международном стандарте.
5) Строго соответствующие программы предназначены для максимальной переносимости среди соответствующих реализаций. Соответствующие программы могут зависеть от непереносимых функций соответствующей реализации.
Примечательно, что для автономной среды, которая фактически определяет какие-либо функции, требуется только заголовок <stdarg.h>
(и даже это могут быть - и часто это - просто макросы).
Стандарт C ++ - Отдельная среда
Так же, как стандарт C признает как размещенную, так и автономную среду, то же самое относится и к стандарту C ++. (Цитаты из ИСО / МЭК 14882: 2011.)
1.4 Соответствие реализации [intro.compliance]
¶7 Определены два вида реализаций: размещенная реализация и автономная реализация . Для размещенной реализации этот международный стандарт определяет набор доступных библиотек. Отдельно стоящий
Реализация - это та, в которой выполнение может происходить без использования операционной системы, и имеет определенный для реализации набор библиотек, который включает в себя определенные библиотеки поддержки языка (17.6.1.3).
¶8 Соответствующая реализация может иметь расширения (включая дополнительные библиотечные функции), при условии, что они не изменяют поведение любой правильно сформированной программы. Реализации необходимы для диагностики программ, которые
использовать такие расширения, которые не соответствуют требованиям настоящего международного стандарта. Сделав это, однако, они могут компилировать и выполнять такие программы.
¶9 Каждая реализация должна включать документацию, которая идентифицирует все условно поддерживаемые конструкции, которые она не поддерживает, и определяет все специфичные для локали характеристики. 3
3) Эта документация также определяет поведение, определяемое реализацией; см. 1.9.
17.6.1.3 Отдельно стоящие реализации [соответствие]
Определены два вида реализаций: размещенный и автономный (1.4). Для размещенной реализации этот международный стандарт описывает набор доступных заголовков.
Автономная реализация имеет набор заголовков, определяемый реализацией. Этот набор должен включать как минимум заголовки, показанные в таблице 16.
В поставляемой версии заголовка <cstdlib>
должны быть объявлены как минимум функции abort
, atexit
, at_quick_exit
, exit
и quick_exit
(18.5). Другие заголовки, перечисленные в этой таблице, должны соответствовать тем же требованиям, что и для размещенной реализации.
Таблица 16 - Заголовки C ++ для автономных реализаций
Subclause Header(s)
<ciso646>
18.2 Types <cstddef>
18.3 Implementation properties <cfloat> <limits> <climits>
18.4 Integer types <cstdint>
18.5 Start and termination <cstdlib>
18.6 Dynamic memory management <new>
18.7 Type identification <typeinfo>
18.8 Exception handling <exception>
18.9 Initializer lists <initializer_list>
18.10 Other runtime support <cstdalign> <cstdarg> <cstdbool>
20.9 Type traits <type_traits>
29 Atomics <atomic>
Как насчет использования int main()
в C?
Стандарт §5.1.2.2.1 стандарта C11 показывает предпочтительное обозначение - int main(void)
- но в стандарте также есть два примера, которые показывают int main()
: §6.5.3.4 ¶8 и §6.7.6.320 . Теперь важно отметить, что примеры не являются «нормативными»; они только иллюстративны. Если в примерах есть ошибки, они не влияют напрямую на основной текст стандарта. Тем не менее, они строго свидетельствуют об ожидаемом поведении, поэтому, если стандарт включает в себя int main()
в качестве примера, он предполагает, что int main()
не запрещен, даже если он не является предпочтительным обозначением.
6.5.3.4 Операторы sizeof
и _Alignof
...
№8 ПРИМЕР 3 ВВ этом примере размер массива переменной длины вычисляется и возвращается из функции:
#include <stddef.h>
size_t fsize3(int n)
{
char b[n+3]; // variable length array
return sizeof b; // execution time sizeof
}
int main()
{
size_t size;
size = fsize3(10); // fsize3 returns 13
return 0;
}